package tbs.framework.async.container;

import cn.hutool.extra.spring.SpringUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.DisposableBean;
import tbs.framework.async.notifiers.ICancelNotifier;
import tbs.framework.async.notifiers.IProgressNotifier;
import tbs.framework.async.notifiers.IResultNotifier;
import tbs.framework.async.task.IAsyncTask;
import tbs.framework.async.task.ICancelable;
import tbs.framework.async.task.IProgressable;
import tbs.framework.async.task.IResultable;
import tbs.framework.utils.IStartup;

import java.util.List;
import java.util.stream.Collectors;

import static tbs.framework.constants.BeanNameConstant.BUILTIN_ASYNC_TASK_SERVICE;

/**
 * 异步任务服务
 *
 * @author Abstergo
 */
public interface IAsyncTaskService extends IStartup, DisposableBean {

    /**
     * 主要异步任务执行器
     *
     * @return
     */
    public static IAsyncTaskService getAsyncTaskService() {
        return SpringUtil.getBean(BUILTIN_ASYNC_TASK_SERVICE);
    }

    /**
     * 获取异步任务代理
     *
     * @return
     */
    @NotNull IAsyncTaskBroker getAsyncTaskBroker();

    /**
     * 通知进度
     *
     * @param service      异步任务服务
     * @param progress     进度值
     * @param progressable 进度可设置对象
     * @param task         异步任务
     */
    public static void notifyProgress(@NotNull IAsyncTaskService service, @NotNull int progress,
        @NotNull IProgressable progressable, @NotNull IAsyncTask task) {
        progressable.setProgress(progress);
        service.getProgressNotifiers()
            .forEach(progressNotifier -> progressNotifier.notifyProgress(progressable, task, service));
    }

    /**
     * 通知取消
     *
     * @param service    异步任务服务
     * @param task       异步任务
     * @param cancelable 可取消对象
     * @param msg        取消信息
     */
    public static void notifyCancel(@NotNull IAsyncTaskService service, @NotNull IAsyncTask task,
        @NotNull ICancelable cancelable, String msg) {
        cancelable.cancel(msg);
        service.getCancelNotifiers()
            .forEach(cancelNotifier -> cancelNotifier.cancelTaskNotify(cancelable, task, service));
    }

    /**
     * 通知结果
     *
     * @param r          结果对象
     * @param service    异步任务服务
     * @param task       异步任务
     * @param resultable 结果可设置对象
     */
    public static void notifyResult(Object r, @NotNull IAsyncTaskService service, @NotNull IAsyncTask task,
        @NotNull IResultable resultable) {
        resultable.setResult(r);
        service.getResultNotifiers().forEach(resultNotifier -> resultNotifier.notifyResult(resultable, task, service));
    }

    /**
     * 获取异步任务容器
     *
     * @return
     */
    IAsyncTaskContainer container();

    /**
     * 获取取消提醒器
     *
     * @return
     */
    default List<ICancelNotifier> getCancelNotifiers() {
        return SpringUtil.getBeansOfType(ICancelNotifier.class).values().stream().collect(Collectors.toList());
    }

    /**
     * 获取进度提醒器
     *
     * @return
     */
    default List<IProgressNotifier> getProgressNotifiers() {
        return SpringUtil.getBeansOfType(IProgressNotifier.class).values().stream().collect(Collectors.toList());
    }

    /**
     * 获取结果提醒器
     *
     * @return
     */
    default List<IResultNotifier> getResultNotifiers() {
        return SpringUtil.getBeansOfType(IResultNotifier.class).values().stream().collect(Collectors.toList());
    }

    /**
     * 启动异步任务服务
     */
    void service();

    /**
     * 停止异步任务服务
     */
    void stop();

    /**
     * 判断异步任务服务是否正在运行
     *
     * @return 异步任务服务是否正在运行
     */
    boolean isService();

    @Override
    default void destroy() throws Exception {
        stop();
    }

    @Override
    default void startUp() throws RuntimeException {
        service();
    }
}
